#pragma once
#include "Animation.h"
#include "Bone.h"
typedef Array<Matrix> BoneMatrices;
class Entity;

//
// struct Skeleton
//
class Skeleton
{
	friend class SkeletonManager;
public:
	AnimationMap Animations;
	BoneCollection Bones;
	
	void SetBindingPose()
	{
		BoneInstanceArray boneInstances(Bones);
		boneInstances.ResetBones();
		boneInstances.UpdateTransform(true);

		for (size_t i = 0; i < boneInstances.Size(); i++)
		{
			BoneInstance& instance = boneInstances.Get(i);
			Bone& bone = Bones.Bones.Get(instance.BaseBone->Index);
			bone.mBindDerivedInversePosition = - instance.DerivedPosition;
			bone.mBindDerivedInverseScale = Vector3::One / instance.DerivedScale;
			bone.mBindDerivedInverseOrientation = instance.DerivedOrientation.Inverse();
		}
	}
	
private:
	Skeleton(const std::string& name) : mName(name) {}
	virtual ~Skeleton() {}
	
	const std::string mName;
};

//
// SkeletonInstance
//
class SkeletonInstance
{
public:
	SkeletonInstance(Entity* parent, const Skeleton* skeleton);
	~SkeletonInstance();

	const BoneMatrices& getBoneMatrices() const { return mBoneMatrices; }

	void Update(float elapsedTime);
	bool EnableAnim(const std::string& name, bool loop = true);

private:
	Entity* mParent;
	const Skeleton* mSkeleton;
	BoneInstanceArray mBoneInstances;
	BoneMatrices mBoneMatrices;
	AnimationStateCollection mAllAnimations;
	
	void UpdateAnimation();
};
